package wms

import (
	"context"
	"ez/apps/wms/auto/mc"
	"fmt"
	"gitee.com/dreamwood/ez-go/db/mgo"
	"gitee.com/dreamwood/ez-go/ez"
	"gitee.com/dreamwood/ez-go/ss"
	"go.mongodb.org/mongo-driver/mongo"
)

func (this *ItemCategory) MakeChoice() *ss.M {
	return &ss.M{
		"value":  this.Id,
		"label":  this.Name,
		"level":  this.Level,
		"parent": this.ParentId,
	}
}
func (this *ItemCategory) MakeTree() (re *ss.M) {
	re = &ss.M{
		"id":       this.Id,
		"title":    this.Name,
		"value":    this.Id,
		"label":    this.Name,
		"children": make([]*ss.M, 0),
	}
	if len(this.Children) == 0 {
		return
	}
	children := make([]*ss.M, 0)
	for _, v := range this.Children {
		v.LoadChildren()
		children = append(children, v.MakeTree())
	}
	(*re)["children"] = children
	return
}

type ItemCategoryCrud struct {
	Factory *mgo.Factory
}

func NewItemCategoryCrud(args ...interface{}) *ItemCategoryCrud {
	factory := mgo.NewFactory(args...)
	factory.SetDoc(&ItemCategory{})
	factory.SetArgus(mc.GetItemCategoryConfig())
	crud := &ItemCategoryCrud{
		Factory: factory,
	}
	return crud
}
func (this *ItemCategoryCrud) GetCollection() *mongo.Collection {
	return this.Factory.GetCollection()
}
func (this *ItemCategoryCrud) FindId(id int64) (*ItemCategory, error) {
	md := new(ItemCategory)
	e := this.Factory.FindId(md, id)
	return md, e
}
func (this *ItemCategoryCrud) FindBy(where ss.M, order []string, page int, limit int) ([]*ItemCategory, error) {
	list := make([]*ItemCategory, 0)
	qb := &ez.HttpQuery{
		Conditions: where,
		Order:      order,
		Page:       page,
		Limit:      limit,
	}
	e := this.Factory.FindBy(&list, qb)
	return list, e
}
func (this *ItemCategoryCrud) FindOneBy(where ss.M, order []string) (*ItemCategory, error) {
	md := new(ItemCategory)
	qb := &ez.HttpQuery{
		Conditions: where,
		Order:      order,
	}
	e := this.Factory.FindOneBy(md, qb)
	return md, e
}

type ItemCategoryTreeModel struct{}

func (this ItemCategoryTreeModel) UpdateLeftAndRight(rootId int64, count int64, level int64) int64 {
	crud := NewItemCategoryCrud()
	cond := ss.M{}
	cond["parentId"] = rootId
	sons, e := crud.FindBy(cond, []string{"sort"}, 0, 0)
	count++
	if e != nil {
		return count
	}
	if len(sons) == 0 {
		return count
	}
	for _, son := range sons {
		son.Level = level
		link, isCircle := this.GetParents(son.Id)
		if isCircle {
			//ez.PrintError(errors.New("闭环循环"))
			ez.LogToConsole("闭环循环")
		}
		son.Link = link
		son.L = count
		son.Save()
		//进入子分类继续
		son.R = this.UpdateLeftAndRight(son.Id, count, level+1)
		count = son.R
		son.Save()
		count++
	}
	return count
}
func (this ItemCategoryTreeModel) ClearDirtyParent() {
	crud := NewItemCategoryCrud()
	all, e := crud.FindBy(ss.M{}, nil, 0, 0)
	if ez.Try(e) {
		return
	}
	ids := make([]int64, 0)
	for _, row := range all {
		ids = append(ids, row.Id)
	}
	missed, e := crud.FindBy(ss.M{"parentId__nin": ids}, nil, 0, 0)
	for _, item := range missed {
		item.ParentId = 0
		item.Save()
	}
}

// 获取父级元素，检测闭环
func (this ItemCategoryTreeModel) GetParents(curId int64) (link string, isCircled bool) {
	crud := NewItemCategoryCrud()
	cur, e := crud.FindId(curId)
	if e != nil {
		ez.LogToConsole(e.Error())
		return
	}
	//闭环检测
	log := make(map[int64]bool)
	for {
		if cur.ParentId == 0 {
			return link, isCircled //没有闭环
		}
		parent, e := crud.FindId(cur.ParentId)
		if e != nil {
			ez.LogToConsole(e.Error())
			return
		}
		if parent == nil {
			return link, isCircled //没有闭环
		}
		//检测到闭环 就直接退出
		logFind, ok := log[parent.Id]
		if ok && logFind {
			isCircled = true
			return link, isCircled
		}
		link = fmt.Sprintf("%d_%s", parent.L, link)
		log[parent.Id] = true
		cur = parent
	}
}

// 绑定一个事件监听
func init() {
	ez.Subscribe(mc.ItemCategoryEventAfterSave, func(v interface{}, ctx context.Context) {
		_, ok := v.(*ItemCategory)
		if ok {
			ItemCategoryTreeModel{}.UpdateLeftAndRight(0, 0, 0)
		}
	})
}
func neverUsed_ItemCategory_func() {
	//导入ss包
	a := ss.M{}
	fmt.Printf("%v", a)
	fmt.Printf("%v", context.TODO())
}
